package com.serviceprovider.business.module.sp.transaction.controller;

import java.beans.PropertyEditor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;

import com.serviceprovider.business.module.admin.role.services.dao.interfaces.IRoleService;
import com.serviceprovider.business.module.admin.settings.services.ISettingsService;
import com.serviceprovider.business.module.admin.user.services.dao.interfaces.IUserService;
import com.serviceprovider.business.module.order.model.Order;
import com.serviceprovider.business.module.order.services.dao.interfaces.IOrderDao;
import com.serviceprovider.business.module.sp.preferences.model.Preferences;
import com.serviceprovider.business.module.sp.preferences.services.IPreferencesService;
import com.serviceprovider.business.module.sp.transaction.model.Batch;
import com.serviceprovider.business.module.sp.transaction.model.FeeItem;
import com.serviceprovider.business.module.sp.transaction.model.TransactionDetail;
import com.serviceprovider.business.module.sp.transaction.model.TransactionUserAmount;
import com.serviceprovider.business.module.sp.transaction.services.dao.interfaces.IBatchDao;
import com.serviceprovider.business.module.sp.transaction.services.dao.interfaces.ITransStatusDao;
import com.serviceprovider.business.module.sp.transaction.services.dao.interfaces.ITransactionUserAmountDao;
import com.serviceprovider.business.module.sp.transaction.services.interfaces.ITransactionService;
import com.serviceprovider.business.module.sp.transaction.services.interfaces.ITransactionUserAmountService;
import com.serviceprovider.business.module.sp.transaction.valueobjects.BatchTransactionVO;
import com.serviceprovider.business.module.sp.transaction.valueobjects.TransactionDetailsVO;
import com.serviceprovider.business.module.user.model.impl.User;
import com.serviceprovider.business.module.user.model.impl.UserSearchCriteria;
import com.serviceprovider.business.utility.Int2DoublePropertyEditor;
import com.serviceprovider.business.utility.RequestConstants;
import com.serviceprovider.business.utility.maintenance.settings.AppSettings;
import com.serviceprovider.business.utility.maintenance.settings.RoleUtils;

/**
 * Controller for the transactions page
 *
 * @author mrduongnv@gmail.com
 */
@Controller
public class ProviderTransactionsController extends SimpleFormController {

    @Qualifier("validator")
    @Autowired
    private Validator validator;

    @Autowired
    private ITransactionService transactionService;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private IUserService userService;

    @Autowired
    IPreferencesService preferencesService;

    @Autowired
    ISettingsService propertiesService;

    @Autowired
    IBatchDao batchDao;

    @Autowired
    ITransStatusDao transactionStatusDao;
    
    @Autowired
    IOrderDao orderDetailDao;

    @Autowired
    ITransactionUserAmountDao transactionUserAmountDao;
    
    @Autowired
    ITransactionUserAmountService transactionUserAmountService;
    //ITransactionPayeeService transactionPayeeService;

    private BatchTransactionVO modelObject;

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        PropertyEditor propertyEditorNullIsZero = new Int2DoublePropertyEditor(true);
        PropertyEditor propertyEditorNullIsNull = new Int2DoublePropertyEditor(false);
        binder.registerCustomEditor(Integer.class, "transactionDetails.amount", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.amounts", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.serviceFee", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.selfFee", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.customerBalance", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.transactionAmounts.amount", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.taxPrepFee", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.electronicPrepFee", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.electronicFillingFee", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.serviceBureauFee", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.miscPayments", propertyEditorNullIsZero);
        binder.registerCustomEditor(Integer.class, "transactionDetails.customLabel1", propertyEditorNullIsNull);
        binder.registerCustomEditor(Integer.class, "transactionDetails.customLabel2", propertyEditorNullIsNull);

        logger.debug("initBinder finished");
    }

    @ModelAttribute("federalFeeList")
    public List<FeeItem> getFederalFeeList() {
        return builFeeItemList(36);
    }

    @ModelAttribute("stateFeeList")
    public List<FeeItem> getStateFeeList() {
        return builFeeItemList(25);
    }

    @RequestMapping(value = RequestConstants.TransactionRequests.SP_NEW_TRANSACTION, method = RequestMethod.GET)
    public ModelAndView getNewTransactions(@RequestParam(value = "continue", required = false) Boolean comeback,
    		@RequestParam(required=false)String sortColumn, @RequestParam(required=false)String sortOrder) {
        ModelAndView mav = new ModelAndView(RequestConstants.TransactionRequests.VIEW_SP_NEW_TRANSACTION);
        if (comeback == null || !comeback){
            	modelObject = createNewModelObject(sortColumn,sortOrder);
        }

        mav.addObject("transactions", modelObject);
        return mav;
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_NEW_TRANSACTION, method = RequestMethod.POST)
    public ModelAndView getSortedTransactions(@RequestParam(value = "continue", required = false) Boolean comeback,
    		@RequestParam(required=false)String sortColumn, @RequestParam(required=false)String sortOrder) {
        ModelAndView mav = new ModelAndView(RequestConstants.TransactionRequests.VIEW_SP_NEW_TRANSACTION);
        
        if (comeback == null || !comeback)
            modelObject = createNewModelObject(sortColumn,sortOrder);

        mav.addObject("transactions", modelObject);
        return mav;
    }

    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1, method = RequestMethod.POST, params = "Approve")
    public ModelAndView getNewTransactionsStep1a(@ModelAttribute("transactions") BatchTransactionVO form,
                                                 BindingResult result) {
    	ModelAndView mav;
        validator.validate(form, result);
		if (result.hasErrors()) {
        	//ModelAndView mav;
        	mav = new ModelAndView(RequestConstants.TransactionRequests.SP_NEW_TRANSACTION_VIEW);
            form.setPayeeMap(modelObject.getPayeeMap());
            return mav;
        }
        for (Integer key : form.getTransactionDetails().keySet()) {
            TransactionDetailsVO t = form.getTransactionDetails().get(key);
            if (!t.getChecked())              // We do not look at non-checked transactions
                continue;
            int customerBalance = t.getAmount() - t.getServiceFee() - t.getSelfFee();
            int i =1;
            TransactionUserAmount transactionPayeeInfo = null;
            List<TransactionUserAmount> list = new ArrayList<TransactionUserAmount>();
            for (int payeeId : t.getAmounts().keySet()) {
                int amount = t.getAmounts().get(payeeId);
                if (amount != 0) {
                    customerBalance -= amount;
                    form.getChosenPayeeMap().put(i, modelObject.getPayeeMap().get(payeeId));
                    i++;
                    // Saving transaction payee information
                    transactionPayeeInfo = new TransactionUserAmount();
                    transactionPayeeInfo.setTransactionId(modelObject.getTransactionDetails().get(key).getId());
                    transactionPayeeInfo.setUserId(modelObject.getPayeeMap().get(payeeId).getId());
                    transactionPayeeInfo.setAmount(amount);
                    list.add(transactionPayeeInfo);
                }
            }
            transactionUserAmountService.deleteAllByTransactionId(modelObject.getTransactionDetails().get(key).getId());
            if(list.size()>0){
            	for (TransactionUserAmount transactionUserAmount : list) {
            		transactionUserAmountService.insert(transactionUserAmount);
				}
            }
            t.setCustomerBalance(customerBalance);
            t.setMiscPayments(t.getAmount() - customerBalance);
            // store aquired data in modelObject
            TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
            tp.setCustomerBalance(customerBalance);
            tp.setMiscPayments(t.getMiscPayments());
            tp.setSelfFee(t.getSelfFee());
            tp.setServiceFee(t.getServiceFee());
            tp.setCustomLabel1(t.getCustomLabel1());
            tp.setCustomLabel2(t.getCustomLabel2());
            tp.setAmounts(t.getAmounts());
            transactionService.updateTransactionStatus(tp.getId(), AppSettings.TRANSACTION_STATUS_STEP1_ID);
            transactionService.updateTransactionSelfFee(tp.getId(), t.getSelfFee());
            transactionService.updateTransactaionCustomerBalance(tp.getId(), customerBalance);
        }
        
       // modelObject = createNewModelObjectbyStatus(AppSettings.TRANSACTION_STATUS_STEP1_ID);
       // mav = new ModelAndView("serviceprovider/transaction/step1");
        //form.setPayeeMap(modelObject.getPayeeMap());
       // mav.addObject("transactions", form );
        return new ModelAndView("redirect:/serviceprovider/transaction/step1.htm");
       // return mav;
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1, method = RequestMethod.GET)
    public ModelAndView TransactionStep1(HttpServletRequest request) {
    	
    	ModelAndView mav;
    	
    	  mav = new ModelAndView(RequestConstants.TransactionRequests.VIEW_SP_TRANSACTION_STEP1);
    	  
    	  modelObject = createNewModelObjectbyStatus(AppSettings.TRANSACTION_STATUS_STEP1_ID);
    	  
    	  String edit = request.getParameter("edit");
    	  if(edit!=null && !edit.trim().isEmpty()){
    		  modelObject.setEditingstep1(true);
    	  }
          mav.addObject("transactions", modelObject);
    	  
          return mav;
      }
      
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2, method = RequestMethod.GET)
    public ModelAndView redirectToNew() {
     
    	ModelAndView mav;
    	
  	    mav = new ModelAndView(RequestConstants.TransactionRequests.VIEW_SP_TRANSACTION_STEP2);
  	  
  	    modelObject = createNewModelObjectbyStatus(AppSettings.TRANSACTION_STATUS_STEP2_ID);

        mav.addObject("transactions", modelObject);
  	  
        return mav;
    }

   @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2, method = RequestMethod.POST, 
		   params = "button_back")
    public ModelAndView goBack(@ModelAttribute("transactions") BatchTransactionVO form) {
        form.setPayeeMap(modelObject.getPayeeMap());
        form.setChosenPayeeMap(modelObject.getChosenPayeeMap());
        form.setTransactionDetails(modelObject.getTransactionDetails());
        modelObject = form;
        
       /* ModelAndView mav;
  	    mav = new ModelAndView("serviceprovider/transaction/step1");
  	    mav.addObject("transactions", modelObject);*/
        return new ModelAndView("redirect:" + RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1);
  	    //return mav;
    }
   @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2, method = RequestMethod.POST, 
		   params = "button_edit")
   public ModelAndView editStep1(@ModelAttribute("transactions") BatchTransactionVO form) {
	   
       form.setPayeeMap(modelObject.getPayeeMap());
       form.setChosenPayeeMap(modelObject.getChosenPayeeMap());
       form.setTransactionDetails(modelObject.getTransactionDetails());
       form.setEditingstep1(true);
       modelObject = form;
       return new ModelAndView("redirect:/serviceprovider/transaction/step1.htm?edit=true");
   }
   
   @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2, method = RequestMethod.POST, 
	   		params = "button_reset")
   public ModelAndView resetransactionsAtStep1(@ModelAttribute("transactions") BatchTransactionVO form, BindingResult result) {
	   for (Integer key : form.getTransactionDetails().keySet()) {
           TransactionDetailsVO t = form.getTransactionDetails().get(key);
           if (!t.getChecked())              // We do not look at non-checked transactions
               continue;
           int customerBalance = t.getAmount() - t.getServiceFee();
           TransactionUserAmount transactionPayeeInfo = null;
           List<TransactionUserAmount> list = new ArrayList<TransactionUserAmount>();
           Map<Integer,Integer> newAmounts = new HashMap<Integer, Integer>();
           for (int payeeId : t.getAmounts().keySet()) {
               Integer amount = t.getAmounts().get(payeeId);
               if (amount != 0) {
                   //form.getChosenPayeeMap().put(payeeId, modelObject.getChosenPayeeMap().get(payeeId));
                   // Saving transaction payee information
                   transactionPayeeInfo = new TransactionUserAmount();
                   transactionPayeeInfo.setTransactionId(modelObject.getTransactionDetails().get(key).getId());
                   transactionPayeeInfo.setUserId(modelObject.getChosenPayeeMap().get(payeeId).getId());
                   transactionPayeeInfo.setAmount(0);
                   list.add(transactionPayeeInfo);
               }
               newAmounts.put(payeeId, 0);
           }
           transactionUserAmountService.deleteAllByTransactionId(modelObject.getTransactionDetails().get(key).getId());
           if(list.size()>0){
           	for (TransactionUserAmount transactionUserAmount : list) {
           		transactionUserAmountService.insert(transactionUserAmount);
				}
           }
           t.setAmounts(newAmounts);
           t.setSelfFee(0);
           
                      
           t.setCustomerBalance(customerBalance);
           t.setMiscPayments(t.getAmount() - customerBalance);
           // store aquired data in modelObject
           TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
           tp.setCustomerBalance(customerBalance);
           tp.setMiscPayments(t.getMiscPayments());
           tp.setSelfFee(0);
           tp.setServiceFee(t.getServiceFee());
           tp.setAmounts(t.getAmounts());
           transactionService.updateTransactionSelfFee(tp.getId(), 0);
           transactionService.updateTransactaionCustomerBalance(tp.getId(), customerBalance);
       }
	   	form.setPayeeMap(modelObject.getPayeeMap());
	    form.setChosenPayeeMap(modelObject.getChosenPayeeMap());
	    form.setTransactionDetails(form.getTransactionDetails());
	    form.setEditingstep1(true);
	    modelObject = form;
	   return new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1_VIEW);   
	   
   }
   
   @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2, method = RequestMethod.POST, 
   		params = "button_save")
   public ModelAndView saveTransactionsAtStep1(@ModelAttribute("transactions") BatchTransactionVO form, BindingResult result) {
	   
	   validator.validate(form, result);
       /*validatePaymentTotal(form, result);*/
       if (result.hasErrors()) {
       	 	form.setPayeeMap(modelObject.getPayeeMap());
            form.setChosenPayeeMap(modelObject.getChosenPayeeMap());
            form.setTransactionDetails(modelObject.getTransactionDetails());
            form.setEditingstep1(true);
            modelObject = form;
           return new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1_VIEW);
       }
	   
	   for (Integer key : form.getTransactionDetails().keySet()) {
           TransactionDetailsVO t = form.getTransactionDetails().get(key);
           if (!t.getChecked())              // We do not look at non-checked transactions
               continue;
           int customerBalance = t.getAmount() - t.getServiceFee() - t.getSelfFee();
           TransactionUserAmount transactionPayeeInfo = null;
           List<TransactionUserAmount> list = new ArrayList<TransactionUserAmount>();
           for (int payeeId : t.getAmounts().keySet()) {
               int amount = t.getAmounts().get(payeeId);
               if (amount != 0) {
                   customerBalance -= amount;
                   //form.getChosenPayeeMap().put(payeeId, modelObject.getChosenPayeeMap().get(payeeId));
                   // Saving transaction payee information
                   transactionPayeeInfo = new TransactionUserAmount();
                   transactionPayeeInfo.setTransactionId(modelObject.getTransactionDetails().get(key).getId());
                   transactionPayeeInfo.setUserId(modelObject.getChosenPayeeMap().get(payeeId).getId());
                   transactionPayeeInfo.setAmount(amount);
                   list.add(transactionPayeeInfo);
               }
           }
           transactionUserAmountService.deleteAllByTransactionId(modelObject.getTransactionDetails().get(key).getId());
           if(list.size()>0){
           	for (TransactionUserAmount transactionUserAmount : list) {
           		transactionUserAmountService.insert(transactionUserAmount);
				}
           }
           
           t.setCustomerBalance(customerBalance);
           t.setMiscPayments(t.getAmount() - customerBalance);
           // store aquired data in modelObject
           TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
           tp.setCustomerBalance(customerBalance);
           tp.setMiscPayments(t.getMiscPayments());
           tp.setSelfFee(t.getSelfFee());
           tp.setServiceFee(t.getServiceFee());
           tp.setAmounts(t.getAmounts());
           //transactionService.updateTransactionStatus(tp.getId(), AppSettings.TRANSACTION_STATUS_STEP2_ID);
           transactionService.updateTransactionSelfFee(tp.getId(), t.getSelfFee());
           transactionService.updateTransactaionCustomerBalance(tp.getId(), customerBalance);
       }
	   	form.setPayeeMap(modelObject.getPayeeMap());
	    form.setChosenPayeeMap(modelObject.getChosenPayeeMap());
	    form.setTransactionDetails(modelObject.getTransactionDetails());
	    form.setEditingstep1(false);
	    modelObject = form;
	   return new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1_VIEW);
   }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2, method = RequestMethod.POST, 
    		params = "button_approve")
    public ModelAndView getNewTransactionsStep2(@ModelAttribute("transactions") BatchTransactionVO form, BindingResult result) {
    	//ModelAndView mav = new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2_VIEW);
        validator.validate(form, result);
        if (result.hasErrors()) {
	       	 form.setPayeeMap(modelObject.getPayeeMap());
	         form.setChosenPayeeMap(modelObject.getChosenPayeeMap());
	         form.setTransactionDetails(modelObject.getTransactionDetails());
	         form.setEditingstep1(true);
	         modelObject = form;
	         return new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1_VIEW);
	    }
        validatePaymentTotal(form, result);
        if (result.hasErrors()) {
        	 form.setPayeeMap(modelObject.getPayeeMap());
             form.setChosenPayeeMap(modelObject.getChosenPayeeMap());
             form.setTransactionDetails(modelObject.getTransactionDetails());
             form.setEditingstep1(true);
             modelObject = form;
            return new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1_VIEW);
        }
        if(form.getEditingstep1()!= null && form.getEditingstep1()){
        	for (Integer key : form.getTransactionDetails().keySet()) {
                TransactionDetailsVO t = form.getTransactionDetails().get(key);
                if (!t.getChecked())              // We do not look at non-checked transactions
                    continue;
                int customerBalance = t.getAmount() - t.getServiceFee() - t.getSelfFee();
                TransactionUserAmount transactionPayeeInfo = null;
                List<TransactionUserAmount> list = new ArrayList<TransactionUserAmount>();
                for (int payeeId : t.getAmounts().keySet()) {
                    int amount = t.getAmounts().get(payeeId);
                    if (amount != 0) {
                        customerBalance -= amount;
                        //form.getChosenPayeeMap().put(payeeId, modelObject.getChosenPayeeMap().get(payeeId));
                        // Saving transaction payee information
                        transactionPayeeInfo = new TransactionUserAmount();
                        transactionPayeeInfo.setTransactionId(modelObject.getTransactionDetails().get(key).getId());
                        transactionPayeeInfo.setUserId(modelObject.getChosenPayeeMap().get(payeeId).getId());
                        transactionPayeeInfo.setAmount(amount);
                        list.add(transactionPayeeInfo);
                    }
                }
                transactionUserAmountService.deleteAllByTransactionId(modelObject.getTransactionDetails().get(key).getId());
                if(list.size()>0){
                	for (TransactionUserAmount transactionUserAmount : list) {
                		transactionUserAmountService.insert(transactionUserAmount);
					}
                }
                
                t.setCustomerBalance(customerBalance);
                t.setMiscPayments(t.getAmount() - customerBalance);
                // store aquired data in modelObject
                TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
                tp.setCustomerBalance(customerBalance);
                tp.setMiscPayments(t.getMiscPayments());
                tp.setSelfFee(t.getSelfFee());
                tp.setServiceFee(t.getServiceFee());
                tp.setAmounts(t.getAmounts());
                transactionService.updateTransactionStatus(tp.getId(), AppSettings.TRANSACTION_STATUS_STEP2_ID);
                transactionService.updateTransactionSelfFee(tp.getId(), t.getSelfFee());
                transactionService.updateTransactaionCustomerBalance(tp.getId(), customerBalance);
            }
        	form.setChosenPayeeMap(modelObject.getChosenPayeeMap());
        }else{
        	for (Integer key : form.getTransactionDetails().keySet()) {
     		   TransactionDetailsVO t = form.getTransactionDetails().get(key);
     		   TransactionDetailsVO tp = null;
     		   if (!t.getChecked()){
     			   // Transactions which are not selected again moved back to transactions new - matched
     			   tp = modelObject.getTransactionDetails().get(key);
     			   transactionService.updateTransactionStatus(tp.getId(),AppSettings.TRANSACTION_STATUS_NEW_ID);
     			   transactionUserAmountService.deleteAllByTransactionId(tp.getId());
     			   continue;
     		   }else{
     			   tp = modelObject.getTransactionDetails().get(key);
     			   transactionService.updateTransactionStatus(tp.getId(),AppSettings.TRANSACTION_STATUS_STEP2_ID);
     		   }
     	   }
     	   form.setPayeeMap(getPayeesMap(userService.getUserConnected().getId()));
        }
        form.setPayeeMap(getPayeesMap(userService.getUserConnected().getId()));
    	
      /*//If new transactions are present then "Approve & Go to place Order" button gets disabled.
        List<TransactionDetail> newTransactions = transactionService.findTransactionsbyStatus(AppSettings.TRANSACTION_STATUS_NEW_ID,userService.getUserConnected().getId());
        if(newTransactions!=null && newTransactions.size()>0){
        	form.setDisableApprovePayments(true);
        }*/
        
       /* mav.addObject(form);
        return mav;*/
        return new ModelAndView("redirect:" + RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2);
    }
    
    private void validatePaymentTotal(BatchTransactionVO form, BindingResult result){
    	for (Integer key : form.getTransactionDetails().keySet()) {
            TransactionDetailsVO t = form.getTransactionDetails().get(key);
            if (!t.getChecked())              // We do not look at non-checked transactions
                continue;
            int customerBalance = t.getAmount() - t.getServiceFee() - t.getSelfFee();
            for (int payeeId : t.getAmounts().keySet()) {
                int amount = t.getAmounts().get(payeeId);
                if (amount != 0) {
                    customerBalance -= amount;
                }
            }
           if(t.getCustomerBalance()!=customerBalance){
        	   result.addError(new FieldError("transactions", "transactionDetails[" + key + "]", "Wrong total fee amount"));
           }
    	}
    	if(result.hasErrors())
     	   result.addError(new FieldError("transactions", "transactionDetails", 
	   			"There seems to be an error in your totals for one (or more rows). Please fix the math total for the row with error message in Red Color."));   
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2, method = RequestMethod.POST)
    public ModelAndView saveTranasctions(@RequestParam(value = "button_new_transactions", required = false) String gotoNewTransactions,
                                         @ModelAttribute("transactions") BatchTransactionVO form,
                                         BindingResult result) {
    	validator.validate(form, result);
    	if (result.hasErrors()) {
            return new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2_VIEW);
        }
        validateMiscPaymentsTotals(form, result);
        if (result.hasErrors()) {
            return new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2_VIEW);
        }
        validateChoosLabels(form,result);
        if (result.hasErrors()) {
            return new ModelAndView(RequestConstants.TransactionRequests.SP_TRANSACTION_STEP2_VIEW);
        }
        // gather data from modelObject and form into form object
        for (Integer key : form.getTransactionDetails().keySet()) {
            TransactionDetailsVO t = form.getTransactionDetails().get(key);
            if (!t.getChecked())              // We do not look at non-checked transactions
                continue;
            TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
            t.setCustomerBalance(tp.getCustomerBalance());
            t.setSelfFee(tp.getSelfFee());
            t.setServiceFee(tp.getServiceFee());
            t.setCustomLabel1(t.getCustomLabel1());
            t.setCustomLabel2(t.getCustomLabel2());
            t.setAmounts(tp.getAmounts());
            t.setId(tp.getId());
            t.setTraceNumber(tp.getTraceNumber());
            t.setOriginatorName(tp.getOriginatorName());
            t.setDataLoadDate(tp.getDataLoadDate());
            form.setProviderId(tp.getUserId());
        }
        
        saveAll(form);
        //Go to place orders or new transaction
        
        return StringUtils.isEmpty(gotoNewTransactions) ?
                new ModelAndView("redirect:/serviceprovider/order/order.htm?orderId="+form.getOrderId()) :
                new ModelAndView("redirect:" + RequestConstants.TransactionRequests.SP_NEW_TRANSACTION);
    }

    private void validateChoosLabels(BatchTransactionVO form, BindingResult result) {
    	boolean chooseColumnLabelRequire1 = false;
    	boolean chooseColumnLabelRequire2 = false;
    	for (Integer key : form.getTransactionDetails().keySet()) {
    		TransactionDetailsVO td = form.getTransactionDetails().get(key);
            if (td != null && td.getChecked() != null && td.getChecked()) {
            		if((td.getCustomLabel1() != null && td.getCustomLabel1() >0) && (form.getCustomLabelName1()==null || form.getCustomLabelName1().trim().isEmpty())){
            			chooseColumnLabelRequire1 = true;
            		}
            		if(td.getCustomLabel2() != null && td.getCustomLabel2() >0 && (form.getCustomLabelName2()==null || form.getCustomLabelName2().trim().isEmpty())){
            			chooseColumnLabelRequire2 = true;
            		}
            }
    	}
    	if(chooseColumnLabelRequire1 )
	    		result.addError(new FieldError("transactions", "customLabelName1", "Please enter label."));
    	
    	if(chooseColumnLabelRequire2 )
	    		result.addError(new FieldError("transactions", "customLabelName2", "Please enter label."));
    	
    	if(chooseColumnLabelRequire1 || chooseColumnLabelRequire2)
			result.addError(new FieldError("transactions", "transactionDetails","Please enter Choose Labels "));
    }
    
    private void validateMiscPaymentsTotals(BatchTransactionVO form, BindingResult result) {
        for (Integer key : form.getTransactionDetails().keySet()) {
            TransactionDetailsVO td = form.getTransactionDetails().get(key);
            if (td != null && td.getChecked() != null && td.getChecked()) {
                int totals = (td.getElectronicFillingFee() == null ? 0 : td.getElectronicFillingFee()) +
                        (td.getElectronicPrepFee() == null ? 0 : td.getElectronicPrepFee()) +
                        (td.getFedBankProductFee() == null ? 0 : td.getFedBankProductFee()) +
                        (td.getCustomLabel1() == null ? 0 : td.getCustomLabel1()) +
                        (td.getCustomLabel2() == null ? 0 : td.getCustomLabel2()) +
                        (td.getStateProductFee() == null ? 0 : td.getStateProductFee()) +
                        (td.getServiceBureauFee() == null ? 0 : td.getServiceBureauFee()) +
                        (td.getTaxPrepFee() == null ? 0 : td.getTaxPrepFee());
                if (totals != td.getMiscPayments()){
                    result.addError(new FieldError("transactions", "transactionDetails[" + key + "]", "Wrong total fee amount"));
                }
            }
        }
        if(result.hasErrors())
        	 result.addError(new FieldError("transactions", "transactionDetails", 
     		"There seems to be an error in your totals for one (or more rows). Please fix the math total for the row with error message in Red Color."));
    }

    /**
     * Create new backing object for the transaction page
     */
    private BatchTransactionVO createNewModelObject(String sortColumn, String sortOrder) {
        BatchTransactionVO result = new BatchTransactionVO();
        
        result.setProviderId(userService.getUserConnected().getId());
        result.setPayeeMap(getPayeesMap(result.getProviderId()));
        Map<Integer, TransactionDetailsVO> map = TransactionDetailsVO.fromList(
        		transactionService.findNewTransactions(result.getProviderId()),sortColumn,sortOrder);
        result.setSortColumn(sortColumn);
        result.setSortOrder(sortOrder);
        result.setTransactionDetails(map);
        
        result.setUserRole(userService.getUserConnected().getRole().getId());

        // Set service fee for the provider. If preferences for given provider doesn't exists then we take fee value from site settings
        Preferences preferences = preferencesService.findByUserId(result.getProviderId());
        int serviceFee;
        if (preferences != null && preferences.getCustomFee() != 0) {
            serviceFee = preferences.getCustomFee();
        } else {
            serviceFee = propertiesService.getDefaultFee();
        }
        // Those are new transactions, clear all the data;
        
        for (TransactionDetailsVO td : result.getTransactionDetails().values()) {
            td.setCustomLabel1(0);
            td.setCustomLabel2(0);
            td.setElectronicFillingFee(0);
            td.setElectronicPrepFee(0);
            td.setFedBankProductFee(0);
            td.setSelfFee(0);
            td.setServiceFee(serviceFee);
            td.setServiceBureauFee(0);
            td.setStateProductFee(0);
            td.setTaxPrepFee(0);

            Map<Integer, Integer> amountsMap = new HashMap<Integer, Integer>();
            for (User payee : result.getPayeeMap().values()) {
                amountsMap.put(payee.getId(), 0);
            }
            td.setAmounts(amountsMap);
        }
        
        List<TransactionDetail> incomplete = transactionService.findTransactionsbyStatus(AppSettings.TRANSACTION_STATUS_STEP1_ID, result.getProviderId());
        if(incomplete!=null && incomplete.size()>0){
        	result.setIsIncompleteTransaction(true);
        	result.setIncompleteStep("step1");
        }/*else{
        	incomplete = transactionService.findTransactionsbyStatus(AppSettings.TRANSACTION_STATUS_STEP2_ID, result.getProviderId());
	        if(incomplete!=null && incomplete.size()>0){
	        	result.setIsIncompleteTransaction(true);
	        	result.setIncompleteStep("step2");
	        }
        }*/

        return result;
    }

    private BatchTransactionVO createNewModelObjectbyStatus(int StatusId) {
        BatchTransactionVO result = new BatchTransactionVO();
        result.setProviderId(userService.getUserConnected().getId());
       
        result.setPayeeMap(getPayeesMap(result.getProviderId()));
        
        result.setTransactionDetails(TransactionDetailsVO.fromList(
    					transactionService.findTransactionsbyStatus(StatusId, result.getProviderId()),
    					AppSettings.TRANSACTION_SORT_COULMN_SSN,AppSettings.TRANSACTION_SORT_ORDER_ASC));
        
     // Set service fee for the provider. 
     // If preferences for given provider doesn't exists then we take fee value from site settings
       Preferences preferences = preferencesService.findByUserId(result.getProviderId());
        int serviceFee;
        if (preferences != null && preferences.getCustomFee() != 0) {
            serviceFee = preferences.getCustomFee();
        } else {
            serviceFee = propertiesService.getDefaultFee();
        }
        
        Map<Integer,User> chosenPayeeMap = new HashMap<Integer, User>();
        for (TransactionDetailsVO td : result.getTransactionDetails().values()) {
            td.setCustomLabel1(0);
            td.setCustomLabel2(0);
            td.setElectronicFillingFee(0);
            td.setElectronicPrepFee(0);
            td.setFedBankProductFee(0);
            td.setSelfFee(td.getSelfFee());
            td.setServiceFee(serviceFee);
            td.setServiceBureauFee(0);
            td.setServiceFee(serviceFee);
            td.setMiscPayments(td.getSelfFee());
            td.setStateProductFee(0);
            td.setTaxPrepFee(0);
            
            Map<Integer, Integer> amountsMap = new HashMap<Integer, Integer>();
            //List<User> payeesList = new ArrayList<User>();
            if(StatusId==AppSettings.TRANSACTION_STATUS_NEW_ID){
            	for (User payee : result.getPayeeMap().values()) {
                    amountsMap.put(payee.getId(), 0);
                }
            }
            if(StatusId==AppSettings.TRANSACTION_STATUS_STEP1_ID){
            	TransactionUserAmount payeeInfo = null;
            	int i=1;
            	for (User payee : result.getPayeeMap().values()) {
                    //amountsMap.put(payee.getId(), 0);
            		payeeInfo = transactionUserAmountService.findPayeeByIds(td.getId(), payee.getId());
            		if(payeeInfo!=null){
            			//payeesList.add(payee);
            			chosenPayeeMap.put(i, payee);
            			amountsMap.put(i, payeeInfo.getAmount());
            			i++;
            		}
                }
            	/*int i=1;
            	for (User user : payeesList) {
            		chosenPayeeMap.put(i, user);
            		i++;
				}*/
            }
            if(StatusId==AppSettings.TRANSACTION_STATUS_STEP2_ID){
            	TransactionUserAmount payeeInfo = null;
            	for (User payee : result.getPayeeMap().values()) {
                    //amountsMap.put(payee.getId(), 0);
            		payeeInfo = transactionUserAmountService.findPayeeByIds(td.getId(), payee.getId());
            		if(payeeInfo!=null){
            			td.setMiscPayments(td.getMiscPayments()+payeeInfo.getAmount());
            		}
                }
            }
            
            td.setAmounts(amountsMap);
            // added
            td.setAmount(td.getAmount());
        }
        result.setChosenPayeeMap(chosenPayeeMap);
        
        //If new transactions are present then "Approve & Go to place Order" button gets disabled.
        List<TransactionDetail> newTransactions = transactionService.findTransactionsbyStatus(AppSettings.TRANSACTION_STATUS_NEW_ID,userService.getUserConnected().getId());
        if(newTransactions!=null && newTransactions.size()>0){
        	result.setDisableApprovePayments(true);
        }
        return result;
    }
    
    private List<FeeItem> builFeeItemList(int maxFee) {
        List<FeeItem> itemList = new ArrayList<FeeItem>();
        for (int i = 1; i < maxFee; i++)
            itemList.add(new FeeItem(i * 100, "$" + i));
        return itemList;
    }

    /**
     * Get payees list for the provider
     *
     * @param providerId - Id of provider to get payees list
     * @return - List of payees for given provider
     */
    private List<User> getPayees(int providerId) {
        UserSearchCriteria criteria = new UserSearchCriteria();
        criteria.setLevel1UserID(providerId);
        criteria.setRoleId(roleService.getRoleId(RoleUtils.ROLE_PAYEE));
        criteria.setInGui(1);
        return userService.findUserByCriteria(criteria, 1, 100, "id", "asc").getPageItems();
    }

    private Map<Integer, User> getPayeesMap(int providerId) {
        List<User> payees = getPayees(providerId);
        Collections.sort(payees);
        Map<Integer, User> payeesMap = new HashMap<Integer, User>();
        int i=1;
        for (User user : payees) {
            //payeesMap.put(user.getId(), user);
        	payeesMap.put(i, user);
        	i++;
        }
        return payeesMap;
    }
    

    /**
     * Save all checked transactions into database
     *
     * @param form - Transactions form to save
     */
    private List<TransactionDetailsVO> saveAll(BatchTransactionVO form) {
        Batch batch = createBatch(form);
        form.setBatchId(batch.getId());
        form.setOrderId(batch.getOrderId());
        return saveTransactionDetailsAndAmounts(form.getTransactionDetails(), batch);
    }

    /**
     * Create new batch object and save it into database
     *
     * @param form - Transaction form with data from which batch object will be created
     * @return New inserted Batch object
     */
    private Batch createBatch(BatchTransactionVO form) {
        Batch batch = new Batch();
        batch.setBatchDate(new Date());
        if (StringUtils.isNotEmpty(form.getCustomLabelName1())) {
            batch.setCustomLabelName1(form.getCustomLabelName1());
        }
        if (StringUtils.isNotEmpty(form.getCustomLabelName2())) {
            batch.setCustomLabelName2(form.getCustomLabelName2());
        }
        if(batch.getOrderId()==null){
        	Integer unplacedOrderId = null;
        	try {
        		unplacedOrderId = orderDetailDao.findUnplacedOrderForUser(form.getProviderId());
			} catch (Exception e) {
				//logger.error("Unplaced order not found",e);
			}
			Order order = null;
			if(unplacedOrderId==null){
	        	logger.info("Order for batch is not present. Creating it");
	        	order = createOrder(form);
	        	batch.setOrderId(order.getId());
			}else{
				batch.setOrderId(unplacedOrderId);
			}
        }
        batch = batchDao.insertBatch(batch);
        //After inserting batch check for  new transactions present or not, if not present then make unplaced order to new
        List<TransactionDetail> newTransactions = transactionService.findNewTransactions(form.getProviderId());
        if(newTransactions == null || newTransactions.size()==0){
        	Integer unplacedOrderId = null;
        	try {
        		unplacedOrderId = orderDetailDao.findUnplacedOrderForUser(form.getProviderId());
			} catch (Exception e) {
				//logger.error("Unplaced order not found",e);
			}
			if(unplacedOrderId!=null){
				// update unplaced order to new order.
				logger.debug("updating order id="+unplacedOrderId+"to new order");
				orderDetailDao.updateStatus(unplacedOrderId, AppSettings.ORDER_STATUS_NEW_ID);
			}
        }
        return batch;
    }
    
    private Order createOrder(BatchTransactionVO form) {
    	Order order = new Order();
    	//order.setCreatedDate(new Date());
    	order.setDate(new Date().toString());
    	order.setInstructions("");
    	order.setMode(1);
    	order.setName("");
    	order.setServiceProviderId(form.getProviderId());
    	order.setTips("");
    	order.getOrderStatus().setId(AppSettings.ORDER_STATUS_UNPLACED_ID);
    	order = orderDetailDao.insertOrder(order);
    	return order;
    }

    /**
     * Save all transaction details and payee amounts into database
     *
     * @param transactionDetails - List of transactions to save
     * @param batch              - Batch that owns saved transactions
     * @return List of saved transactions
     */
    private List<TransactionDetailsVO> saveTransactionDetailsAndAmounts(Map<Integer, TransactionDetailsVO> transactionDetails, Batch batch) {
        List<TransactionDetailsVO> result = new ArrayList<TransactionDetailsVO>();

        for (TransactionDetailsVO data : transactionDetails.values()) {
            // We save only checked transactions
            if (data != null && data.getChecked() != null && data.getChecked()) {
                TransactionDetail transaction = new TransactionDetail();
                TransactionDetailsVO details = null;
                for (TransactionDetailsVO vo : modelObject.getTransactionDetails().values())
                    if (vo.getId().equals(data.getId())) {
                        details = vo;
                        break;
                    }
                if (details == null)
                    return new ArrayList<TransactionDetailsVO>();
                
                transaction.setId(details.getId());
                transaction.setUserId(details.getUserId());
                transaction.setBatch(batch);
                transaction.setTraceNumber(details.getTraceNumber());
                transaction.setTransactionStatus(transactionStatusDao.findByName("Approved"));
                transaction.setAmount(details.getAmount());
                transaction.setCustomerName(details.getCustomerName());
                transaction.setOriginatorName(details.getOriginatorName());
                transaction.setCustomerSSN(details.getCustomerSSN());
                transaction.setDataLoadDate(details.getDataLoadDate());
                transaction.setServiceFee(details.getServiceFee());
                transaction.setSelfFee(details.getSelfFee());

                transaction.setTaxPrepFee(data.getTaxPrepFee());
                transaction.setElectronicPrepFee(data.getElectronicPrepFee());
                transaction.setElectronicFillingFee(data.getElectronicFillingFee());
                transaction.setServiceBureauFee(data.getServiceBureauFee());
                transaction.setFedBankProductFee(data.getFedBankProductFee());
                transaction.setStateProductFee(data.getStateProductFee());
                transaction.setCustomLabel1(data.getCustomLabel1());
                transaction.setCustomLabel2(data.getCustomLabel2());
                transaction.setCustomerBalance(data.getCustomerBalance());

                transactionService.updateTransaction(transaction);

                // we take amount from stale object
               // saveTransactionAmounts(batch.getId(), details.getId(), details.getAmounts());
                updateTransactionAmounts(transaction);
                result.add(details);
            }
        }

        return result;
    }
    
    private void updateTransactionAmounts(TransactionDetail transactionDetail){
    	transactionUserAmountService.updateAll(transactionDetail);
    }

    /**
     * Save payee amounts into database
     *
     * @param batchId            - Id of batch who owns given transaction
     * @param transactionId      - Id of transaction who owns payee amounts
     * @param transactionAmounts - List of amounts to save
     */
    private void saveTransactionAmounts(Integer batchId, Integer transactionId, Map<Integer, Integer> transactionAmounts) {
        for (Integer payeeId : transactionAmounts.keySet()) {
            if (transactionAmounts.get(payeeId) == 0)
                continue;

            TransactionUserAmount transactionUserAmount = new TransactionUserAmount();

            transactionUserAmount.setAmount(transactionAmounts.get(payeeId));
            transactionUserAmount.setBatchId(batchId);
            transactionUserAmount.setTransactionId(transactionId);
            transactionUserAmount.setUserId(payeeId);

            transactionUserAmountDao.insert(transactionUserAmount);
        }
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_NEED_MATCH, method = RequestMethod.GET)
    public ModelAndView getNewTransactionsNeedingMatch(@RequestParam(value = "continue", required = false) Boolean comeback) {
        ModelAndView mav = new ModelAndView(RequestConstants.TransactionRequests.VIEW_SP_TRANSACTION_NEED_MATCH);

        if (comeback == null || !comeback)
            modelObject = createNewModelObjectbyStatus(AppSettings.TRANSACTION_STATUS_NEEDING_MATCH);

        mav.addObject("transactions", modelObject);
        return mav;
    }
    
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_DO_NOT_BELONG, method = RequestMethod.GET)
    public ModelAndView getTransactionsDoNotBelongToMe(@RequestParam(value = "continue", required = false) Boolean comeback) {
        ModelAndView mav = new ModelAndView(RequestConstants.TransactionRequests.VIEW_SP_TRANSACTION_DO_NOT_BELONG);

        if (comeback == null || !comeback)
            modelObject = createNewModelObjectbyStatus(AppSettings.TRANSACTION_STATUS_DO_NOT_BELONG_TO_ME);

        mav.addObject("transactions", modelObject);
        return mav;
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_RETURN_BACK, method = RequestMethod.GET)
    public ModelAndView getTransactionsNeedingToBeReturnedBack(@RequestParam(value = "continue", required = false) Boolean comeback) {
        ModelAndView mav = new ModelAndView(RequestConstants.TransactionRequests.VIEW_SP_TRANSACTION_RETURN_BACK);

        if (comeback == null || !comeback)
            modelObject = createNewModelObjectbyStatus(AppSettings.TRANSACTION_STATUS_NEEDING_RETURN_BACK_TO_ORIGINATOR);

        mav.addObject("transactions", modelObject);
        return mav;
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1, 
    		method = RequestMethod.POST, params = "button_Move_To_New_Matched")
    public ModelAndView moveInNewTransactionsNeedingMatch(@ModelAttribute("transactions") BatchTransactionVO form,
                                                 BindingResult result) {
    	List<Integer> listId = new ArrayList<Integer>();
    	for (Integer key : form.getTransactionDetails().keySet()) {
    		TransactionDetailsVO t = form.getTransactionDetails().get(key);
            if (!t.getChecked())              // We do not look at non-checked transactions
                continue;
            TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
            listId.add(tp.getId());
            //transactionService.updateTransactionStatus(tp.getId(), AppSettings.TRANSACTION_STATUS_NEW_ID);
    	}
    	transactionService.moveTransactionsToNew(listId);
    	
    	return new ModelAndView("redirect:" + RequestConstants.TransactionRequests.SP_NEW_TRANSACTION);
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1, 
    		method = RequestMethod.POST, params = "button_Move_To_Do_Not_belong")
    public ModelAndView moveInTransactionsDoNotBelongToMe(@ModelAttribute("transactions") BatchTransactionVO form,
                                                 BindingResult result) {
    	
    	for (Integer key : form.getTransactionDetails().keySet()) {
    		TransactionDetailsVO t = form.getTransactionDetails().get(key);
            if (!t.getChecked())              // We do not look at non-checked transactions
                continue;
            TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
            transactionService.updateTransactionStatus(tp.getId(), AppSettings.TRANSACTION_STATUS_DO_NOT_BELONG_TO_ME);
    	}
    	return new ModelAndView("redirect:" + RequestConstants.TransactionRequests.SP_TRANSACTION_DO_NOT_BELONG);
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1, 
    		method = RequestMethod.POST, params = "button_Move_To_Needing_To_Return")
    public ModelAndView moveInTransactionsNeedingToReturnedBack(@ModelAttribute("transactions") BatchTransactionVO form,
                                                 BindingResult result) {
    	
    	for (Integer key : form.getTransactionDetails().keySet()) {
    		TransactionDetailsVO t = form.getTransactionDetails().get(key);
            if (!t.getChecked())              // We do not look at non-checked transactions
                continue;
            TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
            transactionService.updateTransactionStatus(tp.getId(), AppSettings.TRANSACTION_STATUS_NEEDING_RETURN_BACK_TO_ORIGINATOR);
    	}
    	return new ModelAndView("redirect:" + RequestConstants.TransactionRequests.SP_TRANSACTION_RETURN_BACK);
    }
    
    @RequestMapping(value = RequestConstants.TransactionRequests.SP_TRANSACTION_STEP1, 
    		method = RequestMethod.POST, params = "button_Move_To_New_Needing_Match")
    public ModelAndView moveInNewTransactionsNeedingAMatch(@ModelAttribute("transactions") BatchTransactionVO form,
                                                 BindingResult result) {
    	
    	for (Integer key : form.getTransactionDetails().keySet()) {
    		TransactionDetailsVO t = form.getTransactionDetails().get(key);
            if (!t.getChecked())              // We do not look at non-checked transactions
                continue;
            TransactionDetailsVO tp = modelObject.getTransactionDetails().get(key);
            transactionService.updateTransactionStatus(tp.getId(), AppSettings.TRANSACTION_STATUS_NEEDING_MATCH);
    	}
    	return new ModelAndView("redirect:" + RequestConstants.TransactionRequests.SP_TRANSACTION_NEED_MATCH);
    }
    
    @RequestMapping(value = {"/serviceprovider/transaction/step1.htm","/serviceprovider/transaction/step2.htm"}, 
    		method = RequestMethod.POST, params = "button_cancel")
    public ModelAndView cancelTransactions(@ModelAttribute("transactions") BatchTransactionVO form,
                                                 BindingResult result) {
    	List<Integer> ids = new ArrayList<Integer>();
    	for (Integer key : form.getTransactionDetails().keySet()) {
  		   TransactionDetailsVO t = form.getTransactionDetails().get(key);
  		   TransactionDetailsVO tp = null;
  		   if (t.getChecked()){
  			   // Transactions which are not selected again moved back to transactions new - matched
  			   tp = modelObject.getTransactionDetails().get(key);
  			  // transactionService.updateTransactionStatus(tp.getId(),AppSettings.TRANSACTION_STATUS_NEW_ID);
  			 ids.add(tp.getId());
  			   //transactionUserAmountService.deleteAllByTransactionId(tp.getId());
  			   continue;
  		   }
  	   }
    	transactionService.moveTransactionsToNewStatus(ids);
    	return new ModelAndView("redirect:/serviceprovider/transaction/new.htm");
    
    }
    
    
}

